package com.xzq.erp.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.xzq.erp.domain.dto.PageDTO;
import com.xzq.erp.domain.dto.ProductDTO;
import com.xzq.erp.domain.po.*;
import com.xzq.erp.domain.query.ProductPageQuery;
import com.xzq.erp.domain.vo.AfterSalesServiceVO;
import com.xzq.erp.domain.vo.IdAndNameVO;
import com.xzq.erp.domain.vo.ProductVO;
import com.xzq.erp.enums.ResponseCodeEnum;
import com.xzq.erp.exception.BizException;
import com.xzq.erp.mapper.*;
import com.xzq.erp.service.IProductService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xzq.erp.utils.JsonUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 商品表 服务实现类
 * </p>
 *
 * @author xzq
 * @since 2025-05-26
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> implements IProductService {

    private final ProductBrandMapper productBrandMapper;

    private final ProductCategoryMapper productCategoryMapper;

    private final SupplierMapper  productSupplierMapper;

    private final ProductUnitMapper productUnitMapper;

    private final ProductOriginMapper productOriginMapper;

    private final ProductStockMapper productStockMapper;


    @Override
    public PageDTO<ProductVO> getProductList(ProductPageQuery query) {
        PageHelper.startPage(query.getCurrent(), query.getSize());
        // 注意Page继承了ArrayList，所以它是个集合对象
        Page<ProductVO> page = this.baseMapper.getProductList(query);// 查询分页查询列表
        List<ProductVO> result = page.getResult();
        List<Long> productIds = result.stream().map(ProductVO::getId).toList();
        if(CollectionUtils.isEmpty(result)){
            return PageDTO.empty(page.getTotal(), (long)page.getPages());
        }
        log.info("查询结果:{},{}", page.getPages(), page.getTotal());
        List<Long> brandIds = result.stream().map(ProductVO::getBrandId).collect(Collectors.toList());
        Map<Long, String> brandMap = productBrandMapper.selectBatchIds(brandIds).stream().collect(Collectors.toMap(ProductBrand::getId, ProductBrand::getName));
        Map<Long, ProductCategory> categoryMap = productCategoryMapper.selectList(null).stream().collect(Collectors.toMap(ProductCategory::getId, p -> p));
        List<Long> supplierIds = result.stream().map(ProductVO::getSupplierId).collect(Collectors.toList());
        Map<Long, String> supplierMap = productSupplierMapper.selectBatchIds(supplierIds).stream().collect(Collectors.toMap(Supplier::getId, Supplier::getName));
        List<Long> unitIds = result.stream().map(ProductVO::getUnitId).collect(Collectors.toList());
        Map<Long, String> unitMap = productUnitMapper.selectBatchIds(unitIds).stream().collect(Collectors.toMap(ProductUnit::getId, ProductUnit::getName));
        List<Long> originIds = result.stream().map(ProductVO::getOriginId).collect(Collectors.toList());
        Map<Long, String> originMap = productOriginMapper.selectBatchIds(originIds).stream().collect(Collectors.toMap(ProductOrigin::getId, ProductOrigin::getName));
        List<ProductStock> productStocks = productStockMapper.selectList(new LambdaQueryWrapper<ProductStock>()
                .in(ProductStock::getProductId, productIds)
                .eq(ProductStock::getStatus, 1)
        );
        Map<Long, List<ProductStock>> map = productStocks.stream().collect(Collectors.groupingBy(ProductStock::getProductId));
        for(ProductVO productVO : result){
            // 设置仓库ID集合
            productVO.setWarehouseId(map.getOrDefault(productVO.getId(), Collections.emptyList()).stream().map(ProductStock::getWarehouseId).collect(Collectors.toList()));
            productVO.setBrandName(brandMap.get(productVO.getBrandId()));
            Long categoryId = productVO.getCategoryId();
            productVO.setCategoryName(categoryMap.get(categoryId).getName());
            // 判断是否存在父级分类
            ProductCategory parentCategory = categoryMap.get(categoryId);
            if(parentCategory!=null && parentCategory.getLevel()!=1){
                productVO.setCategoryParentName(categoryMap.get(parentCategory.getParentId()).getName());
                productVO.setCategoryParentId(parentCategory.getParentId());
            }
            productVO.setSupplierName(supplierMap.get(productVO.getSupplierId()));
            productVO.setUnitName(unitMap.get(productVO.getUnitId()));
            productVO.setOriginName(originMap.get(productVO.getOriginId()));
        }
        
        return PageDTO.of(page);
    }

    @Override
    @Transactional
    public void addProduct(ProductDTO productDTO) {
        Product product = BeanUtil.toBean(productDTO, Product.class);
        this.save(product);
        List<ProductStock> productStockList = productDTO.getWarehouseId().stream().map(warehouseId -> new ProductStock().setProductId(product.getId()).setWarehouseId(warehouseId)).collect(Collectors.toList());
        productStockMapper.insertProductStock(productStockList);
    }

    @Override
    public ProductVO getProductById(Long id) {
        Product product = lambdaQuery()
                .eq(Product::getId, id)
                .one();
        LambdaQueryWrapper<ProductStock> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ProductStock::getProductId, id);
        List<ProductStock> productStocks = productStockMapper.selectList(wrapper);
        ProductVO vo = BeanUtil.toBean(product, ProductVO.class);
        if(CollUtil.isNotEmpty(productStocks)){
            List<Long> warehouseIds = productStocks.stream().map(ProductStock::getWarehouseId).collect(Collectors.toList());
            vo.setWarehouseId(warehouseIds);
        }
        return vo;
    }

    @Override
    @Transactional
    public void updateProduct(ProductDTO productDTO) {
        if(productDTO.getId()==null){
            throw new BizException(ResponseCodeEnum.PARAM_NOT_VALID);
        }
        Product product = BeanUtil.toBean(productDTO, Product.class);
        this.updateById(product);
        productStockMapper.delete(new LambdaQueryWrapper<ProductStock>().eq(ProductStock::getProductId, product.getId()));
        List<ProductStock> productStockList = productDTO.getWarehouseId().stream().map(warehouseId -> new ProductStock().setProductId(product.getId()).setWarehouseId(warehouseId)).collect(Collectors.toList());
        productStockMapper.insertProductStock(productStockList);
    }

    @Override
    @Transactional
    public void deleteProducts(List<Long> ids) {
        this.removeByIds(ids);
        // 删除库存
        productStockMapper.delete(new LambdaQueryWrapper<ProductStock>().in(ProductStock::getProductId, ids));
    }

    @Override
    public void updateProductStatus(Long id, Integer status) {
        lambdaUpdate()
                .eq(Product::getId, id)
                .set(Product::getStatus, status == 1)
                .update();
    }

    @Override
    public List<ProductVO> getAllProducts() {
        ProductPageQuery query = new ProductPageQuery();
        query.setCurrent(1);
        query.setSize(0);
        PageDTO<ProductVO> page = this.getProductList(query);
        List<ProductVO> vos = page.getList();
        if (CollUtil.isEmpty(vos)) {
            return Collections.emptyList();
        }
        return vos;
    }

    @Override
    public List<IdAndNameVO> getProductsByName(String name) {
        if(StrUtil.isBlank(name)){
            return Collections.emptyList();
        }
        return lambdaQuery()
                .like(Product::getName, name)
                .select(Product::getId, Product::getName)
                .list()
                .stream()
                .map(product -> new IdAndNameVO().setId(product.getId()).setName(product.getName()))
                .collect(Collectors.toList());
    }
}
